#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# vim: set et sw=4 ts=4 sts=4 ff=unix fenc=utf8:
# Author: Binux<i@binux.me>
#         http://binux.me
# Created on 2014-10-19 15:37:46

import time
import json
import logging
import traceback
from six.moves import queue as Queue
logger = logging.getLogger("result")


class ResultWorker(object):

    """
    do with result
    override this if needed.
    """

    def __init__(self, resultdb, errordb, inqueue):
        self.resultdb = resultdb
        self.errordb = errordb
        self.inqueue = inqueue
        self._quit = False

    def on_result(self, task, result):
        '''Called every result'''
        if not result:
            return
        result.pop('keyword', [])
        if 'taskid' in task and 'project' in task and 'url' in task:
            logger.info('result %s:%s %s -> %.30r' % (
                task['project'], task['taskid'], task['url'], result))
            try:
                if result.get('file', '') and result.get('file_size', 0) and result.get('file_type', ''):
                    return self.resultdb.save_file(
                        project=task['project'],
                        taskid=task['taskid'],
                        url=task['url'],
                        file=result['file'],
                        file_type=result['file_type'],
                        file_size=result['file_size'],
                        file_name=result.get('file_name', '')
                    )
                else:
                    return self.resultdb.save(
                        project=task['project'],
                        taskid=task['taskid'],
                        url=task['url'],
                        result=result
                    )
            except Exception as e:
                task['track'] = {
                    'db': {
                        'ok': False,
                        'exception': repr(e),
                        'logs': traceback.format_exc()
                    }
                }
                task['result'] = result
                task['errortype'] = self.errordb.DB_ERROR

                self.errordb.insert(task['project'], task['taskid'], task)
            return None

        else:
            logger.warning('result UNKNOW -> %.30r' % result)
            return

    def quit(self):
        self._quit = True

    def run(self):
        '''Run loop'''
        logger.info("result_worker starting...")

        while not self._quit:
            try:
                task, result = self.inqueue.get(timeout=1)
                self.on_result(task, result)
            except Queue.Empty as e:
                continue
            except KeyboardInterrupt:
                break
            except AssertionError as e:
                logger.error(e)
                continue
            except Exception as e:
                logger.exception(e)
                continue

        logger.info("result_worker exiting...")


class OneResultWorker(ResultWorker):
    '''Result Worker for one mode, write results to stdout'''
    def on_result(self, task, result):
        '''Called every result'''
        if not result:
            return
        if 'taskid' in task and 'project' in task and 'url' in task:
            logger.info('result %s:%s %s -> %.30r' % (
                task['project'], task['taskid'], task['url'], result))
            print(json.dumps({
                'taskid': task['taskid'],
                'project': task['project'],
                'url': task['url'],
                'result': result,
                'updatetime': time.time()
            }))
        else:
            logger.warning('result UNKNOW -> %.30r' % result)
            return
